package com.example.service.impl;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import com.example.dto.ClassStudentDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.dto.ApiResponse;
import com.example.dto.ClassRequest;
import com.example.dto.InviteCodeResponse;
import com.example.entity.Class;
import com.example.entity.ClassStudent;
import com.example.mapper.ClassMapper;
import com.example.mapper.ClassStudentMapper;
import com.example.service.ClassService;

/**
 * 班级服务实现类
 * 实现ClassService接口，提供班级相关的业务逻辑实现
 */
@Service
public class ClassServiceImpl implements ClassService {
    // 班级数据访问接口
    @Autowired
    private ClassMapper classMapper;
    // 班级学生关系数据访问接口
    @Autowired
    private ClassStudentMapper classStudentMapper;

    /**
     * 获取系统中所有班级列表
     * @return 包含所有班级的列表，若无班级则返回空列表
     */
    @Override
    public List<Class> getAllClasses() {
        return classMapper.selectList(null);
    }

    /**
     * 获取指定教师的所有授课班级列表
     *
     * @param teacherId 教师的ID
     * @return 包含指定教师授课班级列表的List，如果没有找到对应的班级列表，则返回空列表
     */
    @Override
    public List<Class> getTeacherClasses(Long teacherId) {
        return classMapper.findByTeacherId(teacherId);
    }

    /**
     * 根据学生ID获取该学生所在的班级列表
     *
     * @param studentId 学生ID
     * @return 学生所在的班级列表
     */
    @Override
    public List<Class> getStudentClasses(Long studentId) {
        return classMapper.findByStudentId(studentId);
    }

    /**
     * 根据ID获取班级详情
     * @param id 班级ID
     * @return 对应的班级对象，若不存在返回null
     */
    @Override
    public Class getClassById(Long id) {
        return classMapper.selectById(id);
    }

    /**
     * 创建新班级
     * @param classRequest 班级创建请求对象
     * @param teacherId 创建者教师ID
     * @return 操作结果，包含成功信息和创建的班级对象
     */
    @Override
    @Transactional
    public ApiResponse<?> createClass(ClassRequest classRequest, Long teacherId) {
        Class classEntity = new Class();
        classEntity.setName(classRequest.getName());
        classEntity.setDescription(classRequest.getDescription());
        classEntity.setCourse(classRequest.getCourse());
        classEntity.setGrade(classRequest.getGrade());
        classEntity.setStartDate(classRequest.getStartDate());
        classEntity.setEndDate(classRequest.getEndDate());
        classEntity.setCapacity(classRequest.getCapacity());
        classEntity.setTeacherId(teacherId);
        classEntity.setStatus("active");
        classEntity.setCreateTime(LocalDateTime.now());
        classEntity.setUpdateTime(LocalDateTime.now());
        
        classMapper.insert(classEntity);
        
        return ApiResponse.success("班级创建成功", classEntity);
    }

    /**
     * 更新班级信息
     * @param id 要更新的班级ID
     * @param classRequest 班级更新请求对象
     * @param teacherId 操作者教师ID
     * @return 操作结果，包含成功信息和更新后的班级对象
     */
    @Override
    @Transactional
    public ApiResponse<?> updateClass(Long id, ClassRequest classRequest, Long teacherId) {
        Class existingClass = classMapper.selectById(id);
        
        if (existingClass == null) {
            return ApiResponse.error("班级不存在");
        }
        
        if (!existingClass.getTeacherId().equals(teacherId)) {
            return ApiResponse.error("您没有权限更新此班级");
        }
        
        existingClass.setName(classRequest.getName());
        existingClass.setDescription(classRequest.getDescription());
        existingClass.setCourse(classRequest.getCourse());
        existingClass.setGrade(classRequest.getGrade());
        existingClass.setStartDate(classRequest.getStartDate());
        existingClass.setEndDate(classRequest.getEndDate());
        existingClass.setCapacity(classRequest.getCapacity());
        existingClass.setUpdateTime(LocalDateTime.now());
        
        classMapper.updateById(existingClass);
        
        return ApiResponse.success("班级更新成功", existingClass);
    }

    /**
     * 删除班级
     * @param id 要删除的班级ID
     * @param teacherId 操作者教师ID
     * @return 操作结果
     */
    @Override
    @Transactional
    public ApiResponse<?> deleteClass(Long id, Long teacherId) {
        Class existingClass = classMapper.selectById(id);
        
        if (existingClass == null) {
            return ApiResponse.error("班级不存在");
        }
        
        if (!existingClass.getTeacherId().equals(teacherId)) {
            return ApiResponse.error("您没有权限删除此班级");
        }
        
        // 删除班级相关的学生关系
        com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<ClassStudent> wrapper = 
            new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<>();
        wrapper.eq("class_id", id);
        classStudentMapper.delete(wrapper);
        
        // 删除班级
        classMapper.deleteById(id);
        
        return ApiResponse.success("班级删除成功", null);
    }

    /**
     * 生成班级邀请码
     * @param classId 班级ID
     * @param teacherId 操作者教师ID
     * @return 邀请码响应对象，包含邀请码和过期时间
     * @throws RuntimeException 当班级不存在或教师无权限时抛出
     */
    @Override
    @Transactional
    public InviteCodeResponse generateInviteCode(Long classId, Long teacherId) {
        Class existingClass = classMapper.selectById(classId);
        
        if (existingClass == null) {
            throw new RuntimeException("班级不存在");
        }
        
        if (!existingClass.getTeacherId().equals(teacherId)) {
            throw new RuntimeException("您没有权限为此班级生成邀请码");
        }
        
        // 生成随机邀请码
        String inviteCode = UUID.randomUUID().toString().substring(0, 8).toUpperCase();
        
        // 设置过期时间为7天后
        LocalDateTime expiry = LocalDateTime.now().plusDays(7);
        
        existingClass.setInviteCode(inviteCode);
        existingClass.setInviteCodeExpiry(expiry);
        existingClass.setUpdateTime(LocalDateTime.now());
        
        classMapper.updateById(existingClass);
        
        return new InviteCodeResponse(inviteCode, expiry);
    }

    /**
     * 通过邀请码加入班级
     * @param inviteCode 邀请码
     * @param studentId 学生ID
     * @return 操作结果
     */
    @Override
    @Transactional
    public ApiResponse<?> joinClassByInviteCode(String inviteCode, Long studentId) {
        Class classEntity = classMapper.findByInviteCode(inviteCode);
        
        if (classEntity == null) {
            return ApiResponse.error("邀请码无效");
        }
        
        if (classEntity.getInviteCodeExpiry() != null && classEntity.getInviteCodeExpiry().isBefore(LocalDateTime.now())) {
            return ApiResponse.error("邀请码已过期");
        }
        
        // 检查学生是否已经在班级中
        ClassStudent existingRelation = classStudentMapper.findByClassIdAndStudentId(classEntity.getId(), studentId);
        
        if (existingRelation != null) {
            if ("active".equals(existingRelation.getStatus())) {
                return ApiResponse.error("您已经是该班级的成员");
            } else {
                // 重新激活关系
                existingRelation.setStatus("active");
                existingRelation.setJoinDate(LocalDateTime.now());
                classStudentMapper.updateById(existingRelation);
                return ApiResponse.success("成功重新加入班级", classEntity);
            }
        }
        
        // 检查班级容量
        if (classEntity.getCapacity() != null) {
            int currentStudentCount = classStudentMapper.countStudentsInClass(classEntity.getId());
            if (currentStudentCount >= classEntity.getCapacity()) {
                return ApiResponse.error("班级已满");
            }
        }
        
        // 添加学生到班级
        ClassStudent relation = new ClassStudent();
        relation.setClassId(classEntity.getId());
        relation.setStudentId(studentId);
        relation.setJoinDate(LocalDateTime.now());
        relation.setStatus("active");
        relation.setJoinMethod("code");
        
        classStudentMapper.insert(relation);
        
        return ApiResponse.success("成功加入班级", classEntity);
    }

    /**
     * 分页查询班级学生列表
     *
     * @param classId 班级ID
     * @param page    页码
     * @param size    每页大小
     * @param query   查询条件(学生姓名)
     * @return 分页结果
     */
    @Override
    public Page<ClassStudentDTO> getClassStudents(Long classId, Integer page, Integer size, String query) {
        Page<ClassStudentDTO> pageRequest = new Page<>(page, size);
        return classStudentMapper.findStudentsInClass(pageRequest, classId, query);
    }

    /**
     * 教师手动添加学生到班级
     * @param classId 班级IDgetClassStatistics
     * @param studentId 学生ID
     * @param teacherId 操作者教师ID
     * @return 操作结果
     */
    @Override
    @Transactional
    public ApiResponse<?> addStudentToClass(Long classId, Long studentId, Long teacherId) {
        Class classEntity = classMapper.selectById(classId);
        
        if (classEntity == null) {
            return ApiResponse.error("班级不存在");
        }
        
        if (!classEntity.getTeacherId().equals(teacherId)) {
            return ApiResponse.error("您没有权限为此班级添加学生");
        }
        
        // 检查学生是否已经在班级中
        ClassStudent existingRelation = classStudentMapper.findByClassIdAndStudentId(classId, studentId);
        
        if (existingRelation != null) {
            if ("active".equals(existingRelation.getStatus())) {
                return ApiResponse.error("该学生已经是班级成员");
            } else {
                // 重新激活关系
                existingRelation.setStatus("active");
                existingRelation.setJoinDate(LocalDateTime.now());
                classStudentMapper.updateById(existingRelation);
                return ApiResponse.success("成功将学生添加到班级", null);
            }
        }
        
        // 检查班级容量
        if (classEntity.getCapacity() != null) {
            int currentStudentCount = classStudentMapper.countStudentsInClass(classId);
            if (currentStudentCount >= classEntity.getCapacity()) {
                return ApiResponse.error("班级已满");
            }
        }
        
        // 添加学生到班级
        ClassStudent relation = new ClassStudent();
        relation.setClassId(classId);
        relation.setStudentId(studentId);
        relation.setJoinDate(LocalDateTime.now());
        relation.setStatus("active");
        relation.setJoinMethod("added_by_teacher");
        
        classStudentMapper.insert(relation);
        
        return ApiResponse.success("成功将学生添加到班级", null);
    }

    /**
     * 从班级移除学生
     * @param classId 班级ID
     * @param studentId 学生ID
     * @param teacherId 操作者教师ID
     * @return 操作结果
     */
    @Override
    @Transactional
    public ApiResponse<?> removeStudentFromClass(Long classId, Long studentId, Long teacherId) {
        Class classEntity = classMapper.selectById(classId);
        
        if (classEntity == null) {
            return ApiResponse.error("班级不存在");
        }
        
        if (!classEntity.getTeacherId().equals(teacherId)) {
            return ApiResponse.error("您没有权限从此班级移除学生");
        }
        
        // 检查学生是否在班级中
        ClassStudent existingRelation = classStudentMapper.findByClassIdAndStudentId(classId, studentId);
        
        if (existingRelation == null || !"active".equals(existingRelation.getStatus())) {
            return ApiResponse.error("该学生不是班级成员");
        }
        
        // 移除学生
        existingRelation.setStatus("removed");
        classStudentMapper.updateById(existingRelation);
        
        return ApiResponse.success("成功从班级移除学生", null);
    }

    /**
     * 获取班级统计信息
     * @param classId 班级ID
     * @return 统计信息Map，包含学生数量、考试数量等信息
     * @throws RuntimeException 当班级不存在时抛出
     */
    @Override
    public Map<String, Object> getClassStatistics(Long classId) {
        // 获取班级信息
        Class classInfo = classMapper.selectById(classId);
        if (classInfo == null) {
            throw new RuntimeException("班级不存在");
        }

        // 获取学生数量
        int studentCount = classStudentMapper.countStudentsInClass(classId);
        System.out.println("学生数量: " + studentCount);
        System.out.println("班级容量: " + classInfo.getCapacity());
        // 计算填充率
        double fillRate = 0.0;
        if (classInfo.getCapacity() != null && classInfo.getCapacity() > 0) {
            fillRate = (double) studentCount / classInfo.getCapacity();
        }
        System.out.println("填充率: " + fillRate);

        Map<String, Object> statistics = new HashMap<>();
        statistics.put("classId", classInfo.getId());
        statistics.put("className", classInfo.getName());
        statistics.put("studentCount", studentCount);
        statistics.put("capacity", classInfo.getCapacity());
        statistics.put("fillRate", Math.round(fillRate * 100.0)); // 保留两位小数
        System.out.println("填充率: " + fillRate);
        return statistics;
    }
} 